package com.hup.utils.commons.exception;

import com.hup.utils.commons.ListUtil;
import com.hup.utils.commons.exception.parser.CommonAppParser;
import com.hup.utils.commons.exception.parser.JdkErrParsers;
import com.hup.utils.commons.exception.parser.SpringMsgParser;
import com.hup.utils.commons.exception.parser.SpringStartMsgParser;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;

/**
 * @author hugan
 * @date 2019/8/3
 */
@SuppressWarnings("rawtypes")
@Log4j2
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AppExceptionHandler {

    private static final ArrayList<ExceptionMsgParser> LST_PARSER = new ArrayList<>();

    static {
        registerParser(new CommonAppParser());
        registerParser(new JdkErrParsers());
        registerParser(new SpringMsgParser());
        registerParser(new SpringStartMsgParser());
    }

    /**
     * <pre>
     * 下面选择性使用
     * registerParser(new SpringDaoMsgParser());
     * registerParser(new MyBatisMsgParser());
     * </pre>
     */
    public static void registerParser(ErrParserRegister register) {
        LST_PARSER.addAll(register.getParsers());
    }

    public static ExceptionMsgParser getParser(Throwable e) {
        return ListUtil.get(LST_PARSER, item -> item.isMatch(e));
    }

    public static ErrInfo handle(Throwable e) {
        return handle(null, e, false, true, log);
    }

    public static ErrInfo handle(Throwable e, Logger logger) {
        return handle(null, e, false, true, logger);
    }

    public static ErrInfo handle(String msgHead, Throwable e) {
        return handle(msgHead, e, false, true, log);
    }

    public static ErrInfo handle(String msgHead, Throwable e, boolean printStackForce, boolean needLog) {
        return handle(msgHead, e, printStackForce, needLog, log);
    }

    public static ErrInfo handleNoLog(Throwable e) {
        return handle(null, e, false, false, log);
    }

    public static ErrInfo handleNoLog(String msgHead, Throwable e) {
        return handle(msgHead, e, false, false, log);
    }

    public static ErrInfo handle(String msgHead, Throwable e, boolean printStackForce, boolean needLog, Logger logger) {
        ErrInfo res;
        ExceptionMsgParser parser = ListUtil.get(LST_PARSER, item -> item.isMatch(e));
        if (parser != null) {
            //noinspection unchecked
            res = parser.getInfo(msgHead, e);
            if (printStackForce && res.getTrace() == null) {
                res.setTrace(TraceHandler.TRACE_HANDLER.getTrace(e));
            }
        } else {
            res = new ErrInfo();
            res.setMsg(msgHead, e.getMessage());
            res.setTrace(TraceHandler.TRACE_HANDLER.getTrace(e));
        }
        if (needLog) {
            logger.error("e=[{}]", res);
        }
        return res;
    }

}
